home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWPart / FWDrCmd.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  21.8 KB  |  738 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWDrCmd.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWDRCMD_H
  13. #include "FWDrCmd.h"
  14. #endif
  15.  
  16. #ifndef FWINTER_H
  17. #include "FWInter.h"
  18. #endif
  19.  
  20. // ----- Framework Includes -----
  21.  
  22. #ifndef FWPART_H
  23. #include "FWPart.h"
  24. #endif
  25.  
  26. #ifndef FWFRAME_H
  27. #include "FWFrame.h"
  28. #endif
  29.  
  30. #ifndef FWDRGDRP_H
  31. #include "FWDrgDrp.h"
  32. #endif
  33.  
  34. #ifndef FWSELECT_H
  35. #include "FWSelect.h"
  36. #endif
  37.  
  38. #ifndef FWEVENT_H
  39. #include "FWEvent.h"
  40. #endif
  41.  
  42. #ifndef FWUTIL_H
  43. #include "FWUtil.h"
  44. #endif
  45.  
  46. #ifndef FWPRESEN_H
  47. #include "FWPresen.h"
  48. #endif
  49.  
  50. #ifndef FWLNKMGR_H
  51. #include "FWLnkMgr.h"
  52. #endif
  53.  
  54. #ifndef FWCONTXT_H
  55. #include "FWContxt.h"
  56. #endif
  57.  
  58. #ifndef FWSESION_H
  59. #include "FWSesion.h"
  60. #endif
  61.  
  62. // ----- OS Layer -----
  63.  
  64. #ifndef FWMENUS_K
  65. #include "FWMenus.k"
  66. #endif
  67.  
  68. #ifndef FWODGEOM_H
  69. #include "FWODGeom.h"
  70. #endif
  71.  
  72. #ifndef FWREGION_H
  73. #include "FWRegion.h"
  74. #endif
  75.  
  76. #ifndef FWBARRAY_H
  77. #include "FWBArray.h"
  78. #endif
  79.  
  80. #ifndef SLODFSTR_K
  81. #include "SLODFStr.k"
  82. #endif
  83.  
  84. #ifndef SLODFSTR_H
  85. #include "SLODFStr.h"
  86. #endif
  87.  
  88. // ----- OpenDoc Includes -----
  89.  
  90. #ifndef SOM_Module_OpenDoc_Commands_defined
  91. #include <CmdDefs.xh>
  92. #endif
  93.  
  94. #ifndef SOM_ODClipboard_xh
  95. #include <Clipbd.xh>
  96. #endif
  97.  
  98. #ifndef SOM_Module_OpenDoc_StdProps_defined
  99. #include <StdProps.xh>
  100. #endif
  101.  
  102. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  103. #include <StdTypes.xh>
  104. #endif
  105.  
  106. #ifndef SOM_ODStorageUnit_xh
  107. #include <StorageU.xh>
  108. #endif
  109.  
  110. #ifndef SOM_ODFacet_xh
  111. #include <Facet.xh>
  112. #endif
  113.  
  114. #ifndef SOM_ODDragAndDrop_xh
  115. #include <DragDrp.xh>
  116. #endif
  117.  
  118. #ifndef SOM_ODDragItemIterator_xh
  119. #include <DgItmIt.xh>
  120. #endif
  121.  
  122. #ifndef _TRANSFORM_
  123. #include <Trnsform.xh>
  124. #endif
  125.  
  126. #ifndef SOM_ODLinkSpec_xh
  127. #include <LinkSpec.xh>
  128. #endif
  129.  
  130. // ----- Macintosh Includes -----
  131.  
  132. #if defined(FW_BUILD_MAC) && !defined(__DRAG__)
  133. #include <Drag.h>
  134. #endif
  135.  
  136. //========================================================================================
  137. //    Runtime Info
  138. //========================================================================================
  139.  
  140. #ifdef FW_BUILD_MAC
  141. #pragma segment odfcommands
  142. #endif
  143.  
  144. FW_DEFINE_AUTO(FW_CDragCommand)
  145. FW_DEFINE_AUTO(FW_CDropCommand)
  146.  
  147. //========================================================================================
  148. // FW_CDragCommand class
  149. //========================================================================================
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // FW_CDragCommand constructor
  153. //----------------------------------------------------------------------------------------
  154.  
  155. FW_CDragCommand::FW_CDragCommand(Environment* ev,
  156.                                  FW_CFrame* frame,
  157.                                  FW_Boolean canUndo) :
  158.     FW_CCommand(ev, FW_kDragCommand, frame, canUndo),
  159.     fSelection(NULL),
  160.     fBeganTransaction(false),
  161.     fDragMoveToAnotherPart(false),
  162.     fDestPartIsDifferent(false)
  163. {
  164.     fDragResult = kODDropFail;
  165.  
  166.     if (GetCanUndo(ev))
  167.     {
  168.         FW_CString undoString;
  169.         FW_CString redoString;
  170.         
  171.         ::FW_PrivLoadUndoStrings(ev, FW_kUndoDropMsg, undoString, redoString);
  172.         SetMenuStrings(ev, undoString, redoString);
  173.         
  174.         SetActionType(ev, kODEndAction);
  175.     }
  176.  
  177.     fSelection = frame->GetPresentation(ev)->GetSelection(ev);
  178.     FW_ASSERT(fSelection != NULL);    // Must have a selection object for drag
  179.     FW_END_CONSTRUCTOR
  180. }
  181.  
  182. //----------------------------------------------------------------------------------------
  183. // FW_CDragCommand destructor
  184. //----------------------------------------------------------------------------------------
  185.  
  186. FW_CDragCommand::~FW_CDragCommand()
  187. {
  188.     FW_START_DESTRUCTOR
  189. }
  190.  
  191. //----------------------------------------------------------------------------------------
  192. // FW_CDragCommand::DoIt
  193. //----------------------------------------------------------------------------------------
  194.  
  195. void FW_CDragCommand::DoIt(Environment* ev)    // Override
  196. {
  197.     if (fDragMoveToAnotherPart)            // it's a move to another part
  198.     {
  199.         if (GetCanUndo(ev))
  200.         {
  201.             SaveUndoState(ev);            
  202.         }
  203.         fSelection->ClearSelection(ev);
  204.     }
  205.     
  206.     // ----- Check for failure, and if so clean up
  207.     if (fDragResult == kODDropFail)                // Drag&Drop operation failed somewhere along the line
  208.     {
  209.         SetCausesChange(ev, FALSE);                // Don't call part->Changed()
  210.         SetCanUndo(ev, FALSE);                    // cancel the Undo!
  211.  
  212.         if (fBeganTransaction)                    // we've already added a Begin action
  213.         {
  214.             AbortTransaction(ev);            // clear unfinished transactions from Undo stack
  215.             fBeganTransaction = FALSE;
  216.         }
  217.     }
  218.     else if (fBeganTransaction && !GetCanUndo(ev))    // fCanUndo was turned off after BeginAction was added
  219.     {
  220.         ODPart* part;
  221.         ODActionData actionData;
  222.         ODActionType actionType;
  223.         ODName actionLabel;
  224.         actionLabel.text._buffer = kODNULL;
  225.         actionData._buffer = kODNULL;
  226.  
  227.         if (fDestPartIsDifferent && fDragResult == kODDropCopy)
  228.         {
  229.             // Check previous action
  230.             if (FW_CSession::GetUndo(ev)->PeekUndoHistory(ev, &part, &actionData, &actionType, &actionLabel))
  231.             {
  232.                 if ((actionType == kODBeginAction) && (actionData._maximum == 0))
  233.                 {
  234.                     // Mary  says this block ensures that there  won't be an undo action when 
  235.                     // a drag-copy to the desktop or other non-opendoc destination is performed
  236.                     // I havnen't seen this assertion fail or seen an inapropriate undo menu
  237.                     // item, so that case may be being handled in some other way.
  238.                     FW_Boolean aborting_empty_transaction_in_FW_CDragCommand_DoIt = false;
  239.                     FW_ASSERT(aborting_empty_transaction_in_FW_CDragCommand_DoIt);
  240.                     
  241.                     // Clear empty Begin transaction from Undo stack
  242.                     AbortTransaction(ev);
  243.                     fBeganTransaction = false;
  244.                 }
  245.             }
  246.         }
  247.         
  248.         if (fBeganTransaction)
  249.         {
  250.             // Add an EndAction to finish the transaction, since Execute won't
  251.             AddAction(ev, kODEndAction, NULL, 0, GetUndoString(ev), GetRedoString(ev));
  252.         }
  253.     }
  254.  
  255.     if (!this->IsDragMoveToAnotherPart(ev))
  256.         this->SetCausesChange(ev, FALSE);
  257.  
  258.     // ----- Finally if undoable save the redo state
  259.     if (GetCanUndo(ev))
  260.         SaveRedoState(ev);
  261. }
  262.  
  263. //----------------------------------------------------------------------------------------
  264. // FW_CDragCommand::CommitDone
  265. //----------------------------------------------------------------------------------------
  266.  
  267. void FW_CDragCommand::CommitDone(Environment* ev)
  268. {
  269.     if (GetCanUndo(ev) && HasAddedAction(ev) && fDragMoveToAnotherPart)
  270.             FreeUndoState(ev);
  271. }
  272.  
  273. //----------------------------------------------------------------------------------------
  274. // FW_CDragCommand::BeginDrag
  275. //----------------------------------------------------------------------------------------
  276.  
  277. void FW_CDragCommand::BeginDrag(Environment* ev, const FW_CMouseEvent& theMouseEvent)
  278. {
  279.     ODPart* destPart = NULL;
  280.     ODDragAndDrop*    drag;
  281.     ODStorageUnit*    dragSU;
  282.  
  283.     // ----- Ask the command to save the dragged content and the undo state-----
  284.     ODFacet* facet = theMouseEvent.GetFacet(ev);
  285.     FW_CFrame* scopeFrame = GetFrame(ev);
  286.     FW_ASSERT(facet->GetFrame(ev) == scopeFrame->GetODFrame(ev));
  287.     
  288.     ODRgnHandle dragRegion = NULL;
  289.     
  290.     // ----- In the following block we focus on the window -----
  291.     {
  292.         FW_CWindowContext wc(ev, facet);
  293.     
  294.         FW_CRect selectionBounds;    // selectionBounds is in content coordinate
  295.  
  296.         // ----- Scope for aqDragShape and aqWindowContentTransform -----
  297.         {
  298.             FW_CAcquiredODShape    aqDragShape(CreateDragShape(ev, facet));
  299.             selectionBounds = FW_GetShapeBoundingBox(ev, aqDragShape);
  300.  
  301.             FW_ContentToWindow(ev, facet, aqDragShape);
  302.  
  303.             dragRegion = ::FW_CopyRegion(::FW_GetShapeRegion(ev, aqDragShape));
  304.         }
  305.         
  306. #ifdef FW_BUILD_MAC
  307.         // ----- dragRegion must be in screen coordinate on the Mac
  308.         Point localToGlobal = {FW_QDGlobals.thePort->portRect.top, FW_QDGlobals.thePort->portRect.left};
  309.         ::LocalToGlobal(&localToGlobal);
  310.         FW_CPoint offset(localToGlobal);
  311.         ::FW_OffsetRegion(dragRegion, offset.x, offset.y);
  312. #endif        
  313.  
  314.         //  ----- Fill Drag and Drop SU with Props n' Vals
  315.         drag = FW_CSession::GetDragAndDrop(ev);
  316.         drag->Clear(ev);
  317.         dragSU = drag->GetContentStorageUnit(ev);
  318.         
  319.         // ----- write out the contents of the drag
  320.         GetPart(ev)->GetDataInterchange(ev)->ExternalizeData(ev, fSelection->GetSelectedContent(ev), scopeFrame, dragSU, FW_kDragAndDropStorage, kODCloneCut);
  321.         
  322.         // ----- save offset between mousedown pt and topLeft pt of selection
  323.         // (must convert to Content coordinates first)
  324.         FW_CPoint mouseDownOffset = theMouseEvent.GetMousePosition(ev, FW_CMouseEvent::kFrame);
  325. //        FW_CFrame* frame = FW_CFrame::ODtoFWFrame(ev, facet->GetFrame(ev));
  326. //        frame->GetContentView(ev)->FrameToViewContent(ev, mouseDownOffset);
  327.         scopeFrame->GetContentView(ev)->FrameToViewContent(ev, mouseDownOffset);
  328.         
  329.         mouseDownOffset -= selectionBounds.TopLeft();
  330.         
  331.         dragSU->AddProperty(ev, kODPropMouseDownOffset)->AddValue(ev, kODPoint);
  332.  
  333.         FW_CByteArray byteArray(&mouseDownOffset, sizeof(FW_CPoint));
  334.         dragSU->SetValue(ev, byteArray);
  335.  
  336.         if (GetCanUndo(ev))                        // post an empty Begin action
  337.         {
  338.             AddAction(ev, kODBeginAction, NULL, 0, GetUndoString(ev), GetRedoString(ev));
  339.             fBeganTransaction = TRUE;
  340.         }
  341.  
  342.         // ----- Write out Link Spec if possible -----
  343.         if (!GetPart(ev)->IsReadOnly(ev))
  344.         {
  345.             FW_CLinkManager* linkMgr = GetPart(ev)->GetLinkManager(ev);
  346.             if (linkMgr && fSelection->IsSelectionLinkable(ev))
  347.             {
  348.                 ODLinkSpec* linkSpec = NULL;
  349.                 FW_VOLATILE(linkSpec);
  350.                 ODUpdateID updateID = FW_CSession::UniqueUpdateID(ev); // need data to put in the link spec
  351.                 FW_CByteArray data(&updateID, sizeof(updateID));
  352.         
  353.                 FW_TRY
  354.                 {
  355.                     linkSpec = GetPart(ev)->GetDraft(ev)->CreateLinkSpec(ev, GetPart(ev)->GetODPart(ev), data);
  356.                     dragSU->AddProperty(ev, kODPropLinkSpec);
  357.                     linkSpec->WriteLinkSpec(ev, dragSU);
  358.                 }
  359.                 FW_CATCH_BEGIN
  360.                 FW_CATCH_EVERYTHING()
  361.                 {
  362.                     // exception occurred - just continue without the link spec
  363.                     delete linkSpec;    // deleting NULL is fine
  364.                     linkSpec = NULL;
  365.                     // FW_THROW_SAME();
  366.                 }
  367.                 FW_CATCH_END
  368.         
  369.                 if (linkSpec)
  370.                 {
  371.                     // Create a link
  372.                     FW_CLinkSource* link = linkMgr->NewLinkSource(ev, updateID, GetPresentation(ev));
  373.                     linkMgr->PrivSetPendingDropLink(ev, link, scopeFrame);
  374.                     delete linkSpec;
  375.                     
  376.                 }
  377.             }
  378.         }
  379.  
  380.         FW_CMouseEvent dragEvent(ev, theMouseEvent);
  381.         ODEventData* eventData = dragEvent.GetPlatformEvent();
  382.         FW_CByteArray dragRegionBArray(&dragRegion, sizeof(dragRegion));        
  383.         FW_CByteArray dragEventBArray(&eventData, sizeof(ODEventData*));
  384.  
  385.         scopeFrame->PrivStartStopDragging(ev, FW_kStartDrag);
  386.  
  387.         FW_TRY
  388.         {
  389.             fDragResult = drag->StartDrag(ev, scopeFrame->GetODFrame(ev), kODDragImageRegionHandle, dragRegionBArray, &destPart, dragEventBArray);
  390.         }
  391.         FW_CATCH_BEGIN
  392.         FW_CATCH_EVERYTHING()
  393.         {
  394.             ::FW_DisposeRegion(dragRegion);
  395.             scopeFrame->PrivStartStopDragging(ev, FW_kDragAborted);
  396.             
  397.             if (destPart)
  398.                 destPart->Release(ev);
  399.             
  400.             FW_THROW_SAME();
  401.         }
  402.         FW_CATCH_END
  403.         
  404.         GetPart(ev)->GetDataInterchange(ev)->PrivDeletePromises(ev, FW_kDragAndDropStorage); // [HLX] ??? delete any drag and drop promises because we wan't need them
  405.  
  406.         // ----- Dispose the Drag region ----- 
  407.         ::FW_DisposeRegion(dragRegion);
  408.         dragRegion = NULL;
  409.  
  410.         // ----- Determine if it was a dragmove to another part
  411.         fDestPartIsDifferent = (destPart != GetPart(ev)->GetODPart(ev));
  412.         fDragMoveToAnotherPart = (fDragResult == kODDropMove) && fDestPartIsDifferent;
  413.         
  414.         // ----- Done Dragging -----
  415.         scopeFrame->PrivStartStopDragging(ev, fDragMoveToAnotherPart ? FW_kDragMove : FW_kDragCopy);
  416.  
  417.         // ----- Release the destination part -----
  418.         if (destPart)
  419.             destPart->Release(ev);
  420.  
  421.         // ----- If was not a DragMove to another part 
  422.         if (!fDragMoveToAnotherPart)    // can only Undo drag-move to another part
  423.             SetCanUndo(ev, FALSE);
  424.     }
  425. }
  426.  
  427. //----------------------------------------------------------------------------------------
  428. // FW_CDragCommand::CreateDragShape
  429. //----------------------------------------------------------------------------------------
  430.  
  431. ODShape* FW_CDragCommand::CreateDragShape(Environment* ev, ODFacet* facet)
  432. {
  433.     FW_ASSERT(facet);
  434.     
  435.     return FW_CopyAndRelease(ev, fSelection->AcquireSelectionOutline(ev, facet, GetFrame(ev)));
  436. }
  437.  
  438. //----------------------------------------------------------------------------------------
  439. // FW_CDragCommand::AbortTransaction
  440. //----------------------------------------------------------------------------------------
  441.  
  442. void FW_CDragCommand::AbortTransaction(Environment* ev)
  443. {
  444.     FW_CSession::GetUndo(ev)->AbortCurrentTransaction(ev);
  445. }
  446.  
  447.  
  448. //========================================================================================
  449. // FW_CDropCommand
  450. //========================================================================================
  451.  
  452. //----------------------------------------------------------------------------------------
  453. // FW_CDropCommand constructor
  454. //----------------------------------------------------------------------------------------
  455.  
  456. FW_CDropCommand::FW_CDropCommand(Environment* ev,
  457.                                  FW_CFrame* frame, 
  458.                                  ODDragItemIterator* dropInfo, 
  459.                                  ODFacet* facet, 
  460.                                  const FW_CPoint& dropPoint,
  461.                                  FW_Boolean canUndo) :
  462.     FW_CCommand(ev, FW_kDropCommand, frame, canUndo),
  463.     FW_MPasteAsHandler(ev, frame),
  464.     fDropItemIterator(dropInfo),
  465.     fFacet(facet),
  466.     fDropPoint(dropPoint),
  467.     fSelection(NULL)
  468. {
  469.     fDroppedInSameFrame = FALSE;
  470.     fDropResult = kODDropFail;
  471.     fSelection = frame->GetPresentation(ev)->GetSelection(ev);
  472.     
  473.     if (GetCanUndo(ev))
  474.     {
  475.         FW_CString undoString;
  476.         FW_CString redoString;
  477.         
  478.         ::FW_PrivLoadUndoStrings(ev, FW_kUndoDropMsg, undoString, redoString);
  479.         SetMenuStrings(ev, undoString, redoString);
  480.     }
  481.  
  482.     FW_ASSERT(fSelection != NULL);    // Must have a selection object for drag
  483.     FW_END_CONSTRUCTOR
  484. }
  485.  
  486. //----------------------------------------------------------------------------------------
  487. // FW_CDropCommand destructor
  488. //----------------------------------------------------------------------------------------
  489.  
  490. FW_CDropCommand::~FW_CDropCommand()
  491. {
  492.     FW_START_DESTRUCTOR
  493. }
  494.  
  495. //----------------------------------------------------------------------------------------
  496. // FW_CDropCommand::DoIt
  497. //----------------------------------------------------------------------------------------
  498.  
  499. FW_DECLARE_THROW_POINT(FW_CDropCommand_DoIt_BeforeHandleDrop)
  500. FW_DECLARE_THROW_POINT(FW_CDropCommand_DoIt_AfterHandleDrop)
  501.  
  502. void FW_CDropCommand::DoIt(Environment* ev)
  503. {
  504.     FW_MDroppableFrame* droppable = GetFrame(ev)->GetDroppable(ev);
  505.     FW_ASSERT(droppable != NULL);
  506.     
  507.     if (!this->IsOKtoEdit(ev) || !droppable->GetCanAcceptDrop(ev))
  508.         fDropResult = kODDropFail;
  509.     else
  510.     {
  511.         if (GetCanUndo(ev))
  512.             SaveUndoState(ev);
  513.             
  514.         FW_TRY 
  515.         {
  516.             FW_CHECK_THROW_POINT (FW_CDropCommand_DoIt_BeforeHandleDrop);
  517.             fDropResult = PrivHandleDrop(ev);
  518.         }
  519.         FW_CATCH_BEGIN
  520.         FW_CATCH_EVERYTHING () 
  521.         {
  522.             if (GetCanUndo(ev))
  523.                 FreeUndoState (ev);
  524.             FW_THROW_SAME ();
  525.         }
  526.         FW_CATCH_END
  527.     }
  528.     FW_CHECK_THROW_POINT (FW_CDropCommand_DoIt_AfterHandleDrop);
  529.  
  530.     if (fDropResult == kODDropFail)            // Drop failed--can't Undo
  531.     {
  532.         if (GetCanUndo(ev))
  533.             FreeUndoState(ev);                // Discard any data saved for Undo
  534.         SetCanUndo(ev, FALSE);                // Don't call AddActionToHistory
  535.         SetCausesChange(ev, FALSE);            // Don't call GetPart(ev)->Changed()
  536.     }
  537.     
  538.     // Now that we've successfully dropped, "protect" it by supressing any subsequent
  539.     // failures. We *don't* rethrow now because undo is less important.
  540.     
  541.     if (GetCanUndo(ev)) 
  542.     {
  543.         FW_TRY 
  544.         {
  545.             SaveRedoState(ev);
  546.         }
  547.         FW_CATCH_BEGIN
  548.         FW_CATCH_EVERYTHING () 
  549.         {
  550.             // Having already called PrivHandleDrop and performed the major work of this
  551.             // command we *really* want to avoid passing exceptions up. It would be nice
  552.             // if we could put up an alert saying that Redo won't be supported, though.
  553.         }
  554.         FW_CATCH_END
  555.     }
  556. }
  557.  
  558. //----------------------------------------------------------------------------------------
  559. // FW_CDropCommand::CommitUndone
  560. //----------------------------------------------------------------------------------------
  561.  
  562. void FW_CDropCommand::CommitUndone(Environment* ev)
  563. {
  564.     if (GetCanUndo(ev) && !IsDragMoveInSameFrame(ev))
  565.             FreeRedoState(ev);
  566. }
  567.  
  568. //----------------------------------------------------------------------------------------
  569. // FW_CDropCommand::DoDrop
  570. //----------------------------------------------------------------------------------------
  571.  
  572. FW_Boolean FW_CDropCommand::DoDrop(    Environment* ev,
  573.                                     ODStorageUnit* dropSU,
  574.                                     const FW_CPoint& mouseDownOffset, 
  575.                                     const FW_CPoint& dropPoint,
  576.                                     FW_Boolean isDropMove,
  577.                                     short itemNumber)
  578. {
  579.     FW_UNUSED(mouseDownOffset);
  580.     FW_UNUSED(dropPoint);
  581.     FW_UNUSED(itemNumber);
  582.     
  583.     return GetPart(ev)->GetDataInterchange(ev)->InternalizeData(ev, 
  584.                                                                 GetPresentation(ev)->GetSelection(ev)->GetSelectedContent(ev), 
  585.                                                                 GetFrame(ev), 
  586.                                                                 dropSU, 
  587.                                                                 FW_kDragAndDropStorage, 
  588.                                                                 (isDropMove ? kODCloneDropMove : kODCloneDropCopy), 
  589.                                                                 GetEmbedInfoPtr(ev)) != FW_kInternalizeFailed;
  590. }
  591.  
  592. //----------------------------------------------------------------------------------------
  593. // FW_CDropCommand::DoDroppedInSameFrame
  594. //----------------------------------------------------------------------------------------
  595.  
  596. FW_Boolean FW_CDropCommand::DoDroppedInSameFrame(Environment* ev,
  597.                                                  ODStorageUnit* dropSU,
  598.                                                  const FW_CPoint& mouseDownOffset, 
  599.                                                  const FW_CPoint& dropPoint)
  600. {
  601.     FW_UNUSED(ev);
  602.     FW_UNUSED(dropSU);
  603.     FW_UNUSED(mouseDownOffset);
  604.     FW_UNUSED(dropPoint);
  605.     
  606.     return FALSE;
  607. }
  608.  
  609. //----------------------------------------------------------------------------------------
  610. // FW_CDropCommand::PrivReadMouseDownOffset
  611. //----------------------------------------------------------------------------------------
  612.  
  613. FW_CPoint FW_CDropCommand::PrivReadMouseDownOffset(Environment* ev, ODStorageUnit *dropSU) const
  614. {
  615.     FW_CPoint mouseDownOffset;
  616.     
  617.     if (dropSU->Exists(ev, kODPropMouseDownOffset, kODPoint, 0))
  618.     {
  619.         dropSU->Focus(ev, kODPropMouseDownOffset, kODPosUndefined, kODPoint, 0, kODPosFirstSib);
  620.         FW_CByteArray byteArray;
  621.         dropSU->GetValue(ev, sizeof(FW_CPoint), byteArray);
  622.         byteArray.CopyBuffer(&mouseDownOffset, sizeof(FW_CPoint));
  623.     }
  624.     
  625.     return mouseDownOffset;
  626. }
  627.  
  628. //----------------------------------------------------------------------------------------
  629. // FW_CDropCommand::PrivHandleDrop
  630. //----------------------------------------------------------------------------------------
  631.  
  632. FW_DECLARE_THROW_POINT (FW_CDropCommand_PrivHandleDrop_AfterFirstDrop);
  633.  
  634. ODDropResult FW_CDropCommand::PrivHandleDrop(Environment* ev)
  635. {
  636.     ODStorageUnit* dropSU;
  637.     ODDropResult dropResult = kODDropFail;        // assume the worst
  638.     FW_Boolean acceptedDrop = true;
  639.     FW_Boolean handledDrop = false;
  640.  
  641.     ODDragAndDrop* drag = FW_CSession::GetDragAndDrop(ev);
  642.     
  643.     unsigned long attributes = drag->GetDragAttributes(ev);
  644.     FW_Boolean isDropMove = (attributes & kODDropIsMove);
  645.     FW_Boolean isDropInSameFrame = (attributes & kODDropIsInSourceFrame);
  646.     FW_Boolean isDropInSamePart = (attributes & kODDropIsInSourcePart);
  647.     
  648.     if (attributes & kODDropIsPasteAs)            // user wants Paste As dialog
  649.     {
  650.         dropSU = fDropItemIterator->First(ev);
  651.         
  652.         acceptedDrop = HandleDropPasteAsDialog(ev, dropSU, handledDrop);
  653.         if (handledDrop && acceptedDrop)
  654.         {
  655.             // ----- Get the Mouse Offset -----
  656.             FW_CPoint mouseDownOffset = PrivReadMouseDownOffset(ev, dropSU);
  657.             
  658.             if (GetNewLink(ev) == NULL)
  659.                 SetCommandID(ev, kODCommandPasteAs);
  660.             else
  661.                 SetCommandID(ev, FW_kPasteWithLinkCommand);
  662.             DoDroppedPasteAs(ev, mouseDownOffset, fDropPoint);
  663.  
  664.             if (GetNewLink(ev) != NULL)    // If the drop created a link, return kODDropCopy regardless of the drop attributes.
  665.                 return kODDropCopy;
  666.         }
  667.         // If the user chose to Merge with Contents without a Link, handledDrop is FALSE
  668.         // and the dropped data will be handled below.
  669.     }
  670.     
  671.     if (!handledDrop)
  672.     {
  673.     /*    Regarding exception handling...
  674.         What happens if we are dropping several items and the first goes OK but a later
  675.         one causes an exception to be thrown? Should we try to undo the previous drops
  676.         or just exit (not having fully cleaned up)? We are not going to clean up, on
  677.         the theory that you probably want dropped objects to stick around. If whoever
  678.         called us assumes that we are going to either completely succeed or completely
  679.         fail (i.e. not exit with a partial state change) then there may be a problem.
  680.         This situation comes up every time we have a loop with a state change in it.
  681.     */
  682.         short itemNumber = 0;
  683.     
  684.         // ----- Iterate thru dropped items
  685.         for (dropSU = fDropItemIterator->First(ev); 
  686.             dropSU && acceptedDrop;
  687.             dropSU = fDropItemIterator->Next(ev))
  688.         {        
  689.             itemNumber++;
  690.  
  691.             // ----- Get the Mouse Offset -----
  692.             FW_CPoint mouseDownOffset = PrivReadMouseDownOffset(ev, dropSU);
  693.             
  694.             // ----- Just make sure we are dealing with the same frame -----
  695.             FW_ASSERT(GetFrame(ev) == FW_CFrame::ODtoFWFrame(ev, fFacet->GetFrame(ev)));
  696.             
  697.             // ----- Check if we were dragging in the same presentation. In this case
  698.             // ----- even if we were dragging accross frames I still want to just call 
  699.             // ----- DoDroppedInSameFrame.
  700.             FW_Boolean samePresentation = (isDropInSamePart) && GetPresentation(ev)->PrivIsDragPending();
  701.             
  702.             // ----- Always try to activate the frame (and the window) -----
  703.             GetFrame(ev)->ActivateWindow(ev, fFacet, TRUE);
  704.  
  705.             fDroppedInSameFrame = ((samePresentation || isDropInSameFrame) && isDropMove);
  706.             
  707.             if (fDroppedInSameFrame)
  708.                 acceptedDrop = DoDroppedInSameFrame(ev, dropSU, mouseDownOffset, fDropPoint);
  709.             else
  710.                 acceptedDrop = DoDrop(ev, dropSU, mouseDownOffset, fDropPoint, isDropMove, itemNumber);
  711.  
  712.             FW_CHECK_THROW_POINT (FW_CDropCommand_PrivHandleDrop_AfterFirstDrop);
  713.         }
  714.     }
  715.  
  716.     // ----- Return drop result
  717.     if (acceptedDrop)
  718.         dropResult = (isDropMove ? kODDropMove : kODDropCopy);
  719.         
  720.     return dropResult;
  721. }
  722.  
  723. //----------------------------------------------------------------------------------------
  724. // FW_CDropCommand::DoDroppedPasteAs
  725. //----------------------------------------------------------------------------------------
  726.  
  727. void FW_CDropCommand::DoDroppedPasteAs(Environment* ev, 
  728.                                        const FW_CPoint& mouseDownOffset, 
  729.                                        const FW_CPoint& dropPoint)
  730. {
  731.     FW_UNUSED(ev);
  732.     FW_UNUSED(mouseDownOffset);
  733.     FW_UNUSED(dropPoint);
  734.  
  735.     // Override to perform post-Drop positioning on the items that were dropped
  736. }
  737.  
  738.